import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.util.PPaintContext;

public class ColorBoxNode extends PNode {
	private float TEXT_X_OFFSET;
	private float TEXT_Y_OFFSET;
	private  Font font;
	private boolean hasWidthFocus;
	private boolean hasHeightFocus;
	private boolean prepareColorCount = false;
	private boolean settingColorCount = false;
	private int week;
	private int day;
	private String hueString;
	private String brightnessString;
	private PCamera camera;
	private float hMin;
	private float hMax;
	private float bMin;
	private float bMax;
	private Color c1;
	private Color c2;
	private GradientPaint boxColor;
	private int gFilter[];
	
	private ArrayList<ColorCount> colorCount = null;
	DbHandler db = null;

	public ColorBoxNode(PCamera c, DbHandler db, int week, int day, float hm, float hM, float bm, float bM, int[] filter) {
		camera = c;
		this.db = db;
		this.week = week;
		this.day = day;
		hMin = hm;
		hMax = hM;
		bMin = bm;
		bMax = bM;
		font = new Font("Arial", Font.PLAIN, (int)(16/camera.getViewScale()));
		TEXT_X_OFFSET = (float)(3/camera.getViewScale());
		TEXT_Y_OFFSET = (float)(20/camera.getViewScale());
		gFilter = filter;
		//float h = (hMax+hMin)/2f;
		//float b = (bMax+bMin)/2f;
		//boxColor = Color.getHSBColor(h, 1, b);
		
		c1 = Color.getHSBColor(hMin, 1, bMax);
		c2 = Color.getHSBColor(hMax, 1, bMin);
		float x1 = (float)this.getGlobalBounds().getX();
		float x2 = (float)(this.getGlobalBounds().getX()+getWidth());
		float y1 = (float)this.getGlobalBounds().getY();
		float y2 = (float)(this.getGlobalBounds().getY()+getHeight());
		boxColor = new GradientPaint(x1,y1,c1,x2,y2,c2);
		
		hueString = "H: " + Math.round(hMin*360) + " - " + Math.round(hMax*360);
		brightnessString = "B: " + Math.round(bMin*100) + " - " + Math.round(bMax*100);
	}

	public int getWeek() {
		return week;
	}

	public int getDay() {
		return day;
	}
	
	public float getHMin() {
		return hMin;
	}
	
	public float getHMax() {
		return hMax;
	}
	
	public float getBMin() {
		return bMin;
	}
	
	public float getBMax() {
		return bMax;
	}

	public boolean hasHeightFocus() {
		return hasHeightFocus;
	}

	public void setHasHeightFocus(boolean hasHeightFocus) {
		this.hasHeightFocus = hasHeightFocus;
	}

	public boolean hasWidthFocus() {
		return hasWidthFocus;
	}

	public void setHasWidthFocus(boolean hasWidthFocus) {
		this.hasWidthFocus = hasWidthFocus;
	}
	
	public void setFilter (int[] filter){
		gFilter = filter;
		if (hasWidthFocus && hasHeightFocus && colorCount!=null && getChildrenCount()==0)
			this.prepareColorCount(gFilter);
		colorCount = null;
	}
	
	public void prepareColorCount(int[] filter) {
		gFilter = filter;
		prepareColorCount = true;
	}
	
	public void setColorCount() {
		if (colorCount == null) {
			colorCount = db.getColorNameCountList(hMin, hMax, bMin, bMax, gFilter);
		}
	}

	@Override
	protected void paint(PPaintContext paintContext) {
		Graphics2D g2 = paintContext.getGraphics();
		boxColor = new GradientPaint((float)getX(),(float)getY(),c1,(float)(getWidth()+getX()),(float)(getHeight()+getY()),c2);
		int strokeSize;
		if (hasWidthFocus && hasHeightFocus){
			strokeSize = 8;
			setPaint(Color.YELLOW);
		}
		else {
			strokeSize = 4;
			setPaint(Color.WHITE);
		}
		g2.setPaint(Color.BLACK);
		g2.setStroke(new BasicStroke(
                (float) (strokeSize+2 / camera.getViewScale())));
		g2.draw(getBoundsReference());
		g2.setPaint(getPaint());
		g2.setStroke(new BasicStroke(
                (float) (strokeSize / camera.getViewScale())));
		g2.draw(getBoundsReference());
		
		g2.setFont(font);

		g2.setPaint(boxColor);
		g2.fill(new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight()));

		if ((bMax+bMin)/2f < 0.85f)
			setPaint(Color.WHITE);
		else
			setPaint(Color.BLACK);
		g2.setPaint(getPaint());

		float y = (float) getY() + TEXT_Y_OFFSET;
		float x = (float) getX() + TEXT_X_OFFSET;
		paintContext.getGraphics().drawString(hueString, x, y);
		paintContext.getGraphics().drawString(brightnessString, x, y+16);
		
		if (settingColorCount) {
			this.setColorCount();
			settingColorCount = false;
			prepareColorCount = false;
		}
		
		if (hasWidthFocus && hasHeightFocus) {			
			paintContext.pushClip(getBoundsReference());
			float xOffset = (float) getX() + 50*TEXT_X_OFFSET;
			float yOffset = (float) getY() + 1.8f*TEXT_Y_OFFSET;
			if (prepareColorCount) {
				g2.drawString("Loading...", xOffset-25*TEXT_X_OFFSET, yOffset+1.5f*TEXT_Y_OFFSET);
				settingColorCount=true;
			}
			if (db != null && colorCount != null) {
				int j = Math.min(colorCount.size(), 10);
				for (int i = 0; i < j; i++) {
					yOffset += 16;
					g2.drawString((i+1)+". "+colorCount.get(i).getName()+" - "+colorCount.get(i).getCount(),
							xOffset, 
							yOffset);                            
				}
			}
            paintContext.popClip(getBoundsReference());
		}
	}
}